﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using CommonWFLibrary;
using DTBuilderLib;
using DTBuilderLib.VisualHierarchyClasses;
using IndicoInterface.SimpleAgendaDataModel;
using System.IO;

namespace DeepTalkWF
{
    /// <summary>
    /// Renders the jpegs for talks to a meeting hierarchy of visuals, ready
    /// to be flattened to a XML file that is input to the sparse image too.
    /// </summary>
	public partial class RenderMeetingToVisuals: LongRunningActivityBase
	{
		public RenderMeetingToVisuals()
		{
			InitializeComponent();
            TimesToRetry = 10;
		}

        /// <summary>
        /// Get/Set the DPI at which we will render the visuals we are creating as background.
        /// Only matters for text rendering, so can be worse than the actual talks if desired!
        /// </summary>
        public int DPI
        {
            get { return (int)GetValue(DPIProperty); }
            set { SetValue(DPIProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DPI.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DPIProperty =
            DependencyProperty.Register("DPI", typeof(int), typeof(RenderMeetingToVisuals), new PropertyMetadata(300));

        /// <summary>
        /// The path where we can create jpegs for the images we are generating as background.
        /// </summary>
        public string TempImagePath
        {
            get { return (string)GetValue(TempImagePathProperty); }
            set { SetValue(TempImagePathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TempImagePath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TempImagePathProperty =
            DependencyProperty.Register("TempImagePath", typeof(string), typeof(RenderMeetingToVisuals), new PropertyMetadata(null));

        /// <summary>
        /// The meeting we are to render
        /// </summary>
        public Meeting MeetingInfo
        {
            get { return (Meeting)GetValue(MeetingInfoProperty); }
            set { SetValue(MeetingInfoProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MeetingInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MeetingInfoProperty =
            DependencyProperty.Register("MeetingInfo", typeof(Meeting), typeof(RenderMeetingToVisuals), new PropertyMetadata(null));

        /// <summary>
        /// The list of slides we should be rendering
        /// </summary>
        public Dictionary<Talk, List<FileInfo>> Slides
        {
            get { return (Dictionary<Talk, List<FileInfo>>)GetValue(SlidesProperty); }
            set { SetValue(SlidesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Slides.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SlidesProperty =
            DependencyProperty.Register("Slides", typeof(Dictionary<Talk, List<FileInfo>>), typeof(RenderMeetingToVisuals), new PropertyMetadata(null));

        /// <summary>
        /// The resulting scene that is rendered.
        /// </summary>
        public Visual Scene
        {
            get { return (Visual)GetValue(SceneProperty); }
            set { SetValue(SceneProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Scene.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SceneProperty =
            DependencyProperty.Register("Scene", typeof(Visual), typeof(RenderMeetingToVisuals), new PropertyMetadata(null));


        /// <summary>
        /// The args we are going to pass into the Run method.
        /// </summary>
        [Serializable]
        public class Args
        {
            public int _dpi; // What is the default DPI we are using for images we generate?
            public string _temp_image_path; // Path were we can store images we have to generate
            public Meeting _meeting; // Meeting we are rendering
            public Dictionary<Talk, List<FileInfo>> _slides;
        }

        [LongRunningGatherArguments]
        public Args Gather()
        {
            Args result = new Args();
            result._dpi = DPI;
            result._meeting = MeetingInfo;
            result._slides = Slides;
            result._temp_image_path = TempImagePath;
            return result;
        }

        /// <summary>
        /// Generate the visual and flatten it to a file...
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        [LongRunningMethod]
        public static Results Run(Args a)
        {
            Results r = new Results();

            LayoutBuilder bld = new LayoutBuilder();
            bld.DPI = a._dpi;
            bld.ImageCreationPath = a._temp_image_path;

            /// Now, create the visual scene.

            r._scene = bld.BuildVisualTreeForAMeeting(a._meeting, a._slides);

            return r;
        }

        /// <summary>
        /// Results of the run
        /// </summary>
        [Serializable]
        public class Results
        {
            public Visual _scene;
        }

        /// <summary>
        /// Stash the result of the long running guy back into the good-old thing-y.
        /// </summary>
        /// <param name="r"></param>
        [LongRunningDistributeArguments]
        public void DistributeResults(Results r)
        {
            Scene = r._scene;
        }
    }
}
